package datasets

import (
	"alex/ptp1588boundaryclock/datatypes"
)

// =====================================================================================================================
// BMC Dataset interface -> needed for BMC Data Comparison Algorithm
// =====================================================================================================================
type BMCDataset interface {
	GetPriority1() uint8
	GetIdentity() *datatypes.ClockIdentity
	GetQuality() *datatypes.ClockQuality
	GetPriority2() uint8
	GetStepsRemoved() uint16
	GetIdentityOfSender() *datatypes.ClockIdentity
	GetIdentityOfReceiver() *datatypes.ClockIdentity
	GetPortNumberOfReceiver() uint16
}

// =====================================================================================================================
// Clock Types
// =====================================================================================================================
const (
	ATOMIC_CLOCK uint8 = 0x10
	GPS = 0x20
	TERRESTRIAL_RADIO = 0x30
	PTP = 0x40
	NTP = 0x50
	HAND_SET = 0x60
	OTHER = 0x90
	INTERNAL_OSCILLATOR = 0xA0
)

type DefaultDS struct {
	// =================================================================================================================
	// Static Members
	// =================================================================================================================
	TwoStepFlag                                bool
	ClockIdentity                              datatypes.ClockIdentity
	NumberPorts                                uint16
	// =================================================================================================================
	// Dynamic Members
	// =================================================================================================================
	ClockQuality                            datatypes.ClockQuality
	// =================================================================================================================
	// Configurable Members
	// =================================================================================================================
	Priority1                                uint8
	Priority2                                uint8
	DomainNumber                             uint8
	SlaveOnly                                bool
}

// Implementing BMCDataset Interface methods
func (d* DefaultDS) GetPriority1() uint8 {
	return d.Priority1
}

func (d* DefaultDS) GetIdentity() *datatypes.ClockIdentity {
	return &d.ClockIdentity
}

func (d* DefaultDS) GetQuality() *datatypes.ClockQuality {
	return &d.ClockQuality
}

func (d* DefaultDS) GetPriority2() uint8 {
	return d.Priority2
}

func (d* DefaultDS) GetStepsRemoved() uint16 {
	return 0
}

func (d* DefaultDS) GetIdentityOfSender() *datatypes.ClockIdentity {
	return &d.ClockIdentity
}

func (d* DefaultDS) GetIdentityOfReceiver() *datatypes.ClockIdentity {
	return &d.ClockIdentity
}

func (d* DefaultDS) GetPortNumberOfReceiver() uint16 {
	return 0
}

type CurrentDS struct {
	// =================================================================================================================
	// Dynamic Members
	// =================================================================================================================
	StepsRemoved                             uint16
	OffsetFromMaster                         datatypes.TimeInterval
	MeanPathDelay                            datatypes.TimeInterval
}

type ParentDS struct {
	// =================================================================================================================
	// Dynamic Members
	// =================================================================================================================
	ParentPortIdentity                         datatypes.PortIdentity
	ParentStats                                bool
	ObservedParentOffsetScaledLogVariance      uint16 // !! COMPUTATION OPTIONAL -> IF NOT ParentSTATS FALSE !!
	// The initialization value shall be 7FFF FFFF16
	ObservedParentClockPhaseRateChange        int32 // !! COMPUTATION OPTIONAL -> IF NOT ParentSTATS FALSE !!
	// The initialization value shall be the defaultDS.clockIdentity member.
	GrandmasterIdentity                        datatypes.ClockIdentity
	// The initialization value shall be the value of the defaultDS.clockQuality member.
	GrandmasterClockQuality                    datatypes.ClockQuality
	// The initialization value shall be the value of the defaultDS.priority1 member.
	GrandmasterPriority1                       uint8
	// The initialization value shall be the value of the parentDS.priority2 member.
	GrandmasterPriority2                       uint8
}

type TimePropertiesDS struct {
	// =================================================================================================================
	// Dynamic Members
	// =================================================================================================================
	CurrentUtcOffset                          int16
	CurrentUtcOffsetValid                     bool
	Leap59                                    bool
	Leap61                                    bool
	// Initialization:
	//	- If the timePropertiesDS.ptpTimescale (see 8.2.4.8) is TRUE and the time and the value of
	// 		timePropertiesDS.currentUtcOffset are traceable to a primary reference at the time of initialization,
	// 		the value shall be TRUE, else
	//	- The value shall be FALSE.
	TimeTraceable                             bool
	// Initialization:
	//	- If the frequency is traceable to a primary reference at the time of initialization the value shall be TRUE
	//	- Else the value shall be FALSE.
	FrequencyTraceable                        bool
	// !! INITIALIZE FIRST !!
	// Initialization:
	//	- If the clock timescale (see 7.2.1) is PTP and this is known at the time of initialization, the value shall
	// 		be set to TRUE, else
	//	- The value shall be FALSE, indicating that the timescale is ARB.
	PtpTimescale                              bool
	// The value of timePropertiesDS.timeSource is the source of time used by the grandmaster clock.
	// Initialization:
	//	- If the timeSource (see 7.6.2.6) is known at the time of initialization, the value shall be set to that value.
	//	- Else the value shall be INTERNAL_OSCILLATOR.
	TimeSource                                uint8
}

func (t* TimePropertiesDS) Init(timeSource uint8) {
	t.TimeSource = timeSource
}

// The number of such data sets shall be the value of defaultDS.numberPorts
type PortDS struct {
	// =================================================================================================================
	// Static Members
	// =================================================================================================================
	// The value of portDS.portIdentity shall be the PortIdentity attribute of the local port; see 7.5.2.
	PortIdentity                            datatypes.PortIdentity
	// =================================================================================================================
	// Dynamic Members
	// =================================================================================================================
	PortState                                 uint8
	LogMinDelayReqInterval                    int8
	PeerMeanPathDelay                         datatypes.TimeInterval
	// =================================================================================================================
	// Configurable Members
	// =================================================================================================================
	LogAnnouncedInterval                       int8
	AnnounceReceiptTimeout                     uint8
	LogSyncInterval                            int8
	// The value of portDS.delayMechanism shall indicate the propagation delay measuring option used by the port in
	// computing <meanPathDelay>. The value shall be taken from the enumeration in Table 9. The initialization value is
	// implementation-specific unless otherwise stated in a PTP profile.
	//	DelayMechansim		Value (hex)		Specification
	//	E2E					01				The port is configured to use the delay request-response mechanism.
	//	P2P					02				The port is configured to use the peer delay mechanism.
	//	DISABLED			FE				The port does not implement the delay mechanism; see NOTE.
	//	NOTE: This value shall not be set by a clock except when the applicable PTP profile specifies that the clock
	// 	syntonize only and that neither path delay mechanism is to be used.
	// NOTE: Subclause 9.1 permits reconfiguration. Autoconfiguration is allowed but is out of scope.
	DelayMechanism                             uint8
	LogMinPdelayReqInterval                    int8
	// Version 2
	VersionNumber                            uint8
}

// Initializes a port and sets its data
func (p* PortDS) Init(identity datatypes.PortIdentity, portState uint8, peerMeanPathDelay datatypes.TimeInterval,
	delayMechanism uint8, versionNumber uint8) {
	p.PortIdentity = identity
	p.PortState = portState
	p.PeerMeanPathDelay = peerMeanPathDelay
	p.DelayMechanism = delayMechanism
	p.VersionNumber = versionNumber
}

// 9.3.2.4
type ForeignDS struct {
	ForeignMasterPortIdentity     datatypes.PortIdentity
	ForeignMasterAnnounceMessages uint8
}
